# -*- coding: utf-8 -*-
"""
Created on Thu Apr 20 18:32:47 2023

@author: 52224
"""

#-----------------------载入必要的库--------------------------------------#
import sys
import numpy as np

#-----------------------Pyvisa通过GPIB连接1500---------------------------#
# import pyvisa
# import time
# rm=pyvisa.ResourceManager()
# print(rm.list_resources())
# B1500=rm.open_resource('GPIB0::18::INSTR') # GPIB0::18::INSTR -> B1500的GPIB地址
# print('Instrument has been connected: \n'+B1500.query('*IDN?'))
# B1500.timeout=60000
# B1500.write('*RST')
# B1500.write('CN')

#----------------------B1500的Range参数查找表-----------------------------#
IRange_Table={'Auto':'0','Limited 1pA':'8','Limited 10pA':'9','Limited 100pA':'10',
              'Limited 1nA':'11','Limited 10nA':'12','Limited 100nA':'13','Limited 1uA':'14',
              'Limited 10uA':'15','Limited 100uA':'16','Limited 1mA':'17','Limited 10mA':'18',
              'Limited 100mA':'19','Limited 1A':'20','Limited 2A':'21','Limited 20A':'22'
              ,'Limited 40A':'23','Fixed 1pA':'-8','Fixed 10pA':'-9','Fixed 100pA':'-10',
              'Fixed 1nA':'-11','Fixed 10nA':'-12','Fixed 100nA':'-13','Fixed 1uA':'-14',
              'Fixed 10uA':'-15','Fixed 100uA':'-16'}
VRange_Table={'Auto':'0','Limited 0.2V':'2','Limited 0.5V':'5','Limited 2V':'20','Limited 5V':'50',
              'Limited 20V':'200','Limited 40V':'400','Limited 100V':'1000','Limited 200V':'2000',
              'Limited 500V':'5000','Limited 1500V':'15000','Limited 3000V':'30000'}
Direction_table={'Single Linear':'1','Single Log':'2','Double Linear':'3','Double Log':'4'}

#--------------------IV_Sweep 函数---------------------------------------#
# IV_sweept(B1500,VAR_setup,Measurement_setup,t_hold=0.0,s_delay=0.0,t_delay=0.0)
# 输入1：B1500 -> Pyvisa打开的仪器变量（本程序17行）
# 输入2：VAR_setup -> 扫描变量设置，最多可以有两个扫描变量（e.g: IDVD）
# 输入3: Measurement_setup -> 测量变量设置，没有软件上限
# 输入4, 5, 6：t_hold, s_delay, t_delay对应EasyExpert的设置参数，一般为默认0
# 输出（np.array）：首行为变量名称，下面为测量数值

#--------------------IV_Sweep函数测试参数示例（双变量扫描）------------------#
# Unit1='4'                     #扫描变量1对应的物理端口为4
# VName1='VD'                   #扫描变量1的名字为VD，注意电压模式的端口命名为V....,电流模式端口命名为I...
# Direction1='Double Linear'    #扫描变量1的方向为Double，并且加电压模式为Linear（更多模式见34）
# Start1=-3.0                   #扫描变量1的起始电压为-3 V
# end1=3.0                      #扫描变量1的终止电压为3 V
# nop1=201                      #扫描变量1的点数目为201（Double的话，实际数据点为201*2）
# Icomp1=1e-2                   #扫描变量1的限流值
# range1='Limited 10uA'         #扫描变量1的测量Range
                                #如果单变量扫描，只需要设置上面一个变量              
# Unit2='5'                     #扫描变量2的物理端口为5
# VName2='VG'                   #同1
# Start2=0.0                    #同1
# step2=0.5                     #扫描变量2设置的是步长，对应扫描变量1设置的是终止电压
# nop2=7                        #同1
# Icomp2=1e-2                   #同1
# range2='Limited 1nA'          #同1
# VAR_setup=[Unit1,VName1,Direction1,Start1,end1,nop1,Icomp1,
#             range1,Unit2,VName2,Start2,step2,nop2,Icomp2,range2] #打包扫描变量，如果单变量扫描，不用第二行
# Unit3='6'                    #测量变量1的物理端口为
# VName3='VS'                  #测量变量1的名称，注意测电流是固定电压名称为V...，测电压是固定电流，名称是I...
# Voltage3=0.0                 #测量变量1的固定电压为0 V
# Icomp3=1e-2                  #测量变量1的限流值
# range3='Limited 10nA'        #测量变量1的Range
# Unit4='7'                    #同1
# IName4='Idummy'              #测量变量2的名称，注意测电压的固定名称为I....
# Current4=1e-6                #测量变量2的固定电流为1e-6 A
# Vcomp4=5                     #测量变量2的限压为5 V
# range4='Limited 5V'          #测量变量2的Range
# Measurement_setup=[Unit3,VName3,Voltage3,Icomp3,range3,Unit4,IName4,
#                     Current4,Vcomp4,range4] #打包测量变量，有几个打包几个
def IV_sweept(B1500,VAR_setup,Measurement_setup,t_hold=0.0,s_delay=0.0,t_delay=0.0,ADC='AIT 1,2,1'):
    #=****初始化设置****=#
    global IRange_Table
    global VRange_Table
    B1500.write('CN')
    B1500.write('FMT 1,1') #文件书写方式设置
    B1500.write('TSC 0') #激活返回时间戳功能
    B1500.write('FL 0') #关闭滤波器功能
    #B1500.write('AV 6,0') #设置ADC工作方式，factor=6，且模式为auto
    B1500.write(ADC) #设置ADC工作方式，factor=6，且模式为auto
    Measure_slot='MM 2'
    #=****设置测量AD参数****=#
    try:
        Unit2=VAR_setup[8]
        Unit1=VAR_setup[0]
        dual_sweep_mode=1
        B1500.write('AAD '+Unit2+',1')
        B1500.write('AAD '+Unit1+',1')
    except:
        Unit1=VAR_setup[0]
        dual_sweep_mode=0
        B1500.write('AAD '+Unit1+',1')
    number_of_measure=0
    while(1):
        try:
            number_of_measure+=1
            locals()['Unit'+str(number_of_measure+2)]=Measurement_setup[number_of_measure*5-5]
            B1500.write('AAD '+locals()['Unit'+str(number_of_measure+2)]+',1')
        except:
            number_of_measure-=1
            break
    #=****设置测量模式和Range****=#
    if dual_sweep_mode == 1:
        B1500.write('CMM '+Unit2+',1')
        B1500.write('CMM '+Unit1+',1')
        Measure_slot+=','+Unit1+','+Unit2
        B1500.write('RI '+Unit1+','+IRange_Table[VAR_setup[7]])
        B1500.write('RI '+Unit2+','+IRange_Table[VAR_setup[14]])
    else:
        B1500.write('CMM '+Unit1+',1')
        B1500.write('RI '+Unit1+','+IRange_Table[VAR_setup[7]])
        Measure_slot+=','+Unit1
    for i in range(1,number_of_measure+1):
        ForceName=Measurement_setup[i*5-4]
        ForceName=ForceName[0]
        if ForceName == 'V':
            B1500.write('CMM '+locals()['Unit'+str(i+2)]+',1')
            Measure_slot+=','+locals()['Unit'+str(i+2)]
            B1500.write('RI '+locals()['Unit'+str(i+2)]+','+IRange_Table[Measurement_setup[i*5-1]])
        elif ForceName == 'I':
            B1500.write('CMM '+locals()['Unit'+str(i+2)]+',2')
            Measure_slot+=','+locals()['Unit'+str(i+2)]
            B1500.write('RV '+locals()['Unit'+str(i+2)]+','+VRange_Table[Measurement_setup[i*5-1]])
    B1500.write(Measure_slot)
    #=****测试模式设置与测试前检查****=#
    err=B1500.query('ERR? 1')
    B1500.write('WT '+str(t_hold)+','+str(s_delay)+','+str(t_delay))
    # B1500.write('WM 2,1')
    if err[0] != '0':
        B1500.write('DZ')
        B1500.write('*RST')
        print("Error135")
        return
    #=****开始电压扫描****=#
    #-单变量扫描
    if dual_sweep_mode==0:
       B1500.write('WV '+Unit1+','+Direction_table[VAR_setup[2]]+
                   ',0,'+str(VAR_setup[3])+','+str(VAR_setup[4])+','+str(VAR_setup[5])+','+str(VAR_setup[6])) 
       #=****设置偏置电压****=#
       for i in range(1,number_of_measure+1):
           ForceName=Measurement_setup[i*5-4]
           ForceName=ForceName[0]
           if ForceName == 'V':
               B1500.write('DV '+locals()['Unit'+str(i+2)]+',0,'+
                           str(Measurement_setup[i*5-3])+','+str(Measurement_setup[i*5-2]))
           elif ForceName == 'I':
               B1500.write('DI '+locals()['Unit'+str(i+2)]+',0,'+
                           str(Measurement_setup[i*5-3])+','+str(Measurement_setup[i*5-2]))
       B1500.write('TSR')
       B1500.write('XE')
       try:
           B1500.query('*OPC?')
           err=B1500.query('ERR? 1')
       except:
           B1500.write('PA')
           B1500.write('AB')
           B1500.write('DZ')
           print('Timeout of setted: '+str(B1500.timeout)+'ms')
           
       B1500.write('DZ')
       if err[0] != '0':
           B1500.write('DZ')
           B1500.write('*RST')
           print("Error166")
           return
       #=****读取数据****=#
       rep=B1500.query('NUB?')
       mret=B1500.read()
       measure_data_num=dual_sweep_mode+1+number_of_measure+1
       mret=mret.split(',')
       i=0
       while(1):
           rows_data=mret[i*measure_data_num:(i+1)*measure_data_num]
           if len(rows_data) < measure_data_num:
               break
           VAR_V=rows_data[measure_data_num-1]
           VAR_V=VAR_V[3:]
           VAR_I=rows_data[0]
           VAR_I=VAR_I[3:]
           # try:
           #     del VAR_M
           # except:
           #     a=1
           for j in range(number_of_measure):
               try:
                   V=Measurement_setup[j*5+2]
                   try:
                       VAR_M.append(str(V))
                   except:
                       VAR_M=[str(V)]    
                   I=rows_data[j+1+dual_sweep_mode]
                   I=I[3:]
                   VAR_M.append(I)    
               except:
                   break
           if dual_sweep_mode == 1:
               VAR2_V = VAR2
               VAR2_I = rows_data[1]
               VAR2_I = VAR2_I[3:]
           try:
               rows_data=[VAR_V,VAR_I,VAR2_V,VAR2_I]
               rows_data+=VAR_M
           except:
               rows_data=[VAR_V,VAR_I]
               rows_data+=VAR_M
           del VAR_M
           rows_data=np.array(rows_data)
           rows_data=rows_data.reshape(1,np.size(rows_data,0))
           try:
               data=np.append(data,rows_data,axis=0)
           except:
               data=rows_data
           i+=1
    #=****多变量扫描****=#
    elif dual_sweep_mode == 1:
        VAR2=VAR_setup[10]
        for j in range(VAR_setup[12]):
            B1500.write('WV '+Unit1+','+Direction_table[VAR_setup[2]]+
                       ',0,'+str(VAR_setup[3])+','+str(VAR_setup[4])+','+str(VAR_setup[5])+','+str(VAR_setup[6]))     
            #=****设置偏置电压****=#
            for i in range(1,number_of_measure+1):
                ForceName=Measurement_setup[i*5-4]
                ForceName=ForceName[0]
                if ForceName == 'V':
                    B1500.write('DV '+locals()['Unit'+str(i+2)]+',0,'+
                                str(Measurement_setup[i*5-3])+','+str(Measurement_setup[i*5-2]))
                elif ForceName == 'I':
                    B1500.write('DI '+locals()['Unit'+str(i+2)]+',0,'+
                                str(Measurement_setup[i*5-3])+','+str(Measurement_setup[i*5-2]))
            B1500.write('DV '+Unit2+',0,'+str(VAR2)+','+str(VAR_setup[13]))
            B1500.write('TSR')
            B1500.write('XE')
            B1500.query('*OPC?')
            B1500.write('DZ')
            err=B1500.query('ERR? 1')
            if err[0] != '0':
                B1500.write('DZ')
                B1500.write('*RST')
                print("Error240")
            #=****读取数据****=#
            rep=B1500.query('NUB?')
            mret=B1500.read()
            measure_data_num=dual_sweep_mode+1+number_of_measure+1
            mret=mret.split(',')
            i=0
            while(1):
                rows_data=mret[i*measure_data_num:(i+1)*measure_data_num]
                if len(rows_data) < measure_data_num:
                    break
                VAR_V=rows_data[measure_data_num-1]
                VAR_V=VAR_V[3:]
                VAR_I=rows_data[0]
                VAR_I=VAR_I[3:]
                # try:
                #     del VAR_M
                # except:
                #     a=1
                for j in range(number_of_measure):
                    try:
                        V=Measurement_setup[j*5+2]
                        try:
                            VAR_M.append(str(V))
                        except:
                            VAR_M=[str(V)]    
                        I=rows_data[j+1+dual_sweep_mode]
                        I=I[3:]
                        VAR_M.append(I)    
                    except:
                        break
                if dual_sweep_mode == 1:
                    VAR2_V = VAR2
                    VAR2_I = rows_data[1]
                    VAR2_I = VAR2_I[3:]
                try:
                    rows_data=[VAR_V,VAR_I,VAR2_V,VAR2_I]
                    rows_data+=VAR_M
                except:
                    rows_data=[VAR_V,VAR_I]
                    rows_data+=VAR_M
                del VAR_M
                rows_data=np.array(rows_data)
                rows_data=rows_data.reshape(1,np.size(rows_data,0))
                try:
                    data=np.append(data,rows_data,axis=0)
                except:
                    data=rows_data
                i+=1
            # try:
            #     mret_all=np.append(mret_all,data,axis=0)
            # except:
            #     mret_all=data
            VAR2+=VAR_setup[11]
    #=****-----------添加返回变量定义---------------****=#
    if dual_sweep_mode == 1:
        title=[VAR_setup[1],VAR_setup[1].replace('V','I'),VAR_setup[9],
               VAR_setup[9].replace('V','I')]
    else:
        title=[VAR_setup[1],VAR_setup[1].replace('V','I')]
    for j in range(number_of_measure):
        try:
            V=Measurement_setup[j*5+1]
            title.append(V)   
            if V[0] == 'V':
                I=V.replace('V','I')
            else:
                I=V.replace('I','V')    
            title.append(I)    
        except:
            break
    title=np.array(title)
    title=title.reshape(1,np.size(title,0))
    mret_all=np.append(title,data,axis=0)
    return mret_all
#-------------------------------------------------------------------#


#--------------------IV_List 函数------------------------------------#
#=****定义测试输入参数****=#
# Unit1='1'
# Name1='Vtop'
# Voltage1=[0.05,0.1,0.15]
# Icomp1=0.1
# Range1='Limited 1nA'
# Unit2='2'
# Name2='Vgate'
# Voltage2=[-5,-5,-5]
# Icomp2=10e-6
# Range2='Limited 1nA'
# Unit3='3'
# Name3='Vbottom'
# Voltage3=[0,0,0]
# Icomp3=0.1
# Range3='Limited 1nA'
# Input_list=[Unit1,Name1,Voltage1,Icomp1,
#             Unit2,Name2,Voltage2,Icomp2,
#             Unit3,Name3,Voltage3,Icomp3]
# Range_list=[Range1,Range2,Range3]
def IV_List(B1500,Input_list,Range_list=0):
    #=****初始化1500测试设置****=#
    B1500.write('FMT 1')
    B1500.write('CN')
    # B1500.write('TSC 1')
    B1500.write('FL 0')
    B1500.write('AV 6,0')
    Measure_slot='MM 1'
    #=****设置各Channel测试参数****=#
    Num_of_channel=int(len(Input_list)/4)
    Num_of_point=len(Input_list[2])
    for i in range(Num_of_channel):
        B1500.write('AAD '+Input_list[i*4]+',1')
        Measure_slot+=','+Input_list[i*4]
        if Range_list == 0:
            if Input_list[i*4+1][0] == 'V':
                B1500.write('CMM '+Input_list[i*4]+',1')
                B1500.write('RI '+Input_list[i*4]+','+IRange_Table['Limited 1nA'])
            elif Input_list[i*4+1][0] == 'I':
                B1500.write('CMM '+Input_list[i*4]+',2')
                B1500.write('RV '+Input_list[i*4]+','+VRange_Table['Limited 0.5V'])
            else:
                print('Wrong variable name!')
                print("Error362")
        else:
            if Input_list[i*4+1][0] == 'V':
                B1500.write('CMM '+Input_list[i*4]+',1')
                B1500.write('RI '+Input_list[i*4]+','+IRange_Table[Range_list[i]])
            elif Input_list[i*4+1][0] == 'I':
                B1500.write('CMM '+Input_list[i*4]+',2')
                B1500.write('RV '+Input_list[i*4]+','+VRange_Table[Range_list[i]])
            else:
                print('Wrong variable name!')
                print("Error372")   
    err=B1500.query('ERR? 1')
    if err[0] != '0':
        B1500.write('DZ')
        print('Error!377')
        
    mret_all=[]
    #=****开始测试****=#
    for i in range(Num_of_point):
        #=****设置电压****=#
        for j in range(Num_of_channel):
            if Input_list[i*4+1][0] == 'V':
                B1500.write('DV '+Input_list[j*4]+',0,'+str(Input_list[j*4+2][i])+','+str(Input_list[j*4+3]))
            elif Input_list[i*4+1][0] == 'I':
                B1500.write('DI '+Input_list[j*4]+',0,'+str(Input_list[j*4+2][i])+','+str(Input_list[j*4+3]))
            else:
                print('Wrong variable name!')
                print("Error389")
        err=B1500.query('ERR? 1')
        B1500.write(Measure_slot)
        if err[0] != '0':
            B1500.write('DZ')
            print('Error!')
            print("Error395")
        B1500.write('XE')
        B1500.query('*OPC?')
        B1500.write('DZ')
        B1500.query('NUB?')
        mret=B1500.read()
        mret=mret[:-1]
        mret=mret.split(',')
        for x in range(Num_of_channel):
            Var1=[Input_list[x*4+2][i],float(mret[x][3:])]
            try:
                Var=Var+Var1
            except:
                Var=Var1
        Var=np.array(Var)
        Var=Var.reshape(1,np.size(Var,0))
        try:
            data=np.append(data,Var,axis=0)
        except:
            data=Var
    for x in range(Num_of_channel):
        title1_V=Input_list[4*x+1]
        if title1_V[0] == 'V':
            title1_I=title1_V.replace('V','I')
        else:
            title1_I=title1_V.replace('I','V')
        title1=[title1_V,title1_I]
        try:
            title=title+title1
        except:
            title=title1
    title=np.array(title)
    title=title.reshape(1,np.size(title,0))
    data=np.append(title,data,axis=0)
    return data
#-------------------------------------------------------------------#
